#include "beep.h"


// |------------------- nBYtes -------------------------| --- interval = 0 (sem repetições) ---------- |
//      tOn1    tOff1   tOn2    tOff2   tOn3    tOff3
// _____########________########________########________

// |------------------- nBYtes -------------------------| -- interval > 0 (com repetições continua) -- |
//      tOn1    tOff1   tOn2    tOff2   tOn3    tOff3
// _____########________########________########________ _______________________________________________ _____########________########________########________ ...

#define nPULSE_BEEPS 3 // Quantidade de beeps emitidos por vez

typedef struct {
	uint tOn; 	// tempo que o beep fique ligado
	uint tOff; 	// tempo que o beep fique desligado
} tPulseBeep;

typedef struct {
	unsigned power:1;	// Aciona ou não a emissão de beeps
	uint type;			// Determina o tipo sonoro
	uint nBeeps;		// Quantos beeps emitidos
	uint index;			// Indece do beep atual para ser emitido
	tPulseBeep pulse[nPULSE_BEEPS]; // registra os tempos de on/off dos beeps
	uint intervalLoad;	// Carregar valor para interval
	uint interval;		// Tempo entre repetições dos beeps. Valor 0 sem repetições
} tBeep, *pBeep;
static tBeep beep;

static void beep_SetType(void);

// -------------------------------------------------------------------------------------------------------------------
// Descrição:	Inicializa o gerenciador de beeps
// -------------------------------------------------------------------------------------------------------------------
void beep_Init(void) {
	beep_SetupPorts();
	beep.power = pdOFF; 	// Mantém desligado e emissão de beeps
}

// -------------------------------------------------------------------------------------------------------------------
// Descrição: Liga o beep para emitir um tipo sonoro
// Parametro Type: tipo beep será emitido
//			beepOFF 				Beep desligado
//			beepCONTINUOUS 			Beep ligado direto
//			beepCONTINUOUS_ONOFF 	Emissão de um beep curto em intervalos
//			beep1SHORTBEEP 			Emissão de um beep curto
//			beep3SHORTBEEP 			Emissão de três beeps curtos
//			beepCONTINUOUS_2xONOFF	Emissão de dois beeps curtos em intervalos
//			beep1LONG2SHORTBEEP		Emissão um beep longo e dois beeps curtos
// -------------------------------------------------------------------------------------------------------------------
void beep_Play(uint type) {
	if (type) {
		beep.type = type;
		beep_SetType();
		beep.power = pdON;
	} else beep.power = pdOFF;
}

// retorna o que está sendo tocado no buzzer
// util caso queira esperar pela emissão completa do tipo de beep e emitir outro tipo
uint beep_Playing (void) {
	if (beep.power == pdON) return beep.type;
	else return 0;
}

// Para qualquer emissão de som
void beep_Stop(void) {
	beep.power = pdOFF;
}


// -------------------------------------------------------------------------------------------------------------------
// Descrição:	Ajusta o controlador a emitir o tipo sonoro
// -------------------------------------------------------------------------------------------------------------------
static void beep_SetType(void) {
	uint x; for(x=0;x<nPULSE_BEEPS;x++) { beep.pulse[x].tOff = 0; beep.pulse[x].tOn = 0;}
	beep.index = 0;
	beep.interval = 0;

	switch(beep.type) {
	case beep1SHORTBEEP:
 		beep.nBeeps = 1; // Emitir 1 beep
 		beep.pulse[0].tOn = 50; // Primeiro beep 50 ms ligado
 		beep.pulse[0].tOff = 50; // Primeiro beep 50 ms desligado
 		beep.intervalLoad = 0; // sem repetições
		break;
	case beep3SHORTBEEP:
		beep.nBeeps = 3; // Emitir 3 beeps
		for(x=0;x<3;x++) { beep.pulse[x].tOff = 50; beep.pulse[x].tOn = 50;} // todos os beeps 50ms ligado e desligado
		beep.intervalLoad = 0; // sem repetições
		break;
	case beepCONTINUOUS_ONOFF:
 		beep.nBeeps = 1; // Emitir 1 beep
 		beep.pulse[0].tOn = 100; // Primeiro beep 100 ms ligado
 		beep.pulse[0].tOff = 800; // Primeiro beep 800 ms desligado
 		beep.intervalLoad = 100; // repetir os beeps a cada 100ms
		break;
	case beepCONTINUOUS_2xONOFF:
		beep.nBeeps = 2; // Emitir 2 beeps
		beep.pulse[0].tOn = 100; // Primeiro beep 100 ms ligado
 		beep.pulse[0].tOff = 100; // Primeiro beep 100 ms desligado
 		beep.pulse[1].tOn = 100; // Segundo beep 100 ms ligado
 		beep.pulse[1].tOff = 100; // Segundo beep 100 ms desligado
 		beep.intervalLoad = 2000; // repetir os beeps a cada 2000ms
		break;
	case beep1LONG2SHORTBEEP:
		beep.nBeeps = 3; // Emitir 3 beeps

 		beep.pulse[0].tOn = 100; // Primeiro beep 100 ms ligado
 		beep.pulse[0].tOff = 100; // Primeiro beep 100 ms desligado
 		beep.pulse[1].tOn = 50; // Segundo beep 50 ms ligado
 		beep.pulse[1].tOff = 50; // Segundo beep 50 ms desligado
 		beep.pulse[2].tOn = 50; // Terceiro beep 50 ms ligado
 		beep.pulse[2].tOff = 50; // Terceiro beep 50 ms desligado
		beep.intervalLoad = 0; // sem repetições
		break;

	default: //beepCONTINUOUS
		break;
	}
}

// -------------------------------------------------------------------------------------------------------------------
// Descrição:	Evento a ser chamado a cada 1ms para control de emissão sonora
// -------------------------------------------------------------------------------------------------------------------
//static uint interval = 0;

void beep_Tick(void) {
	// Se não é para emitir som, vamos desligar o buzzer e sair fora
	if (beep.power == pdOFF) {
		beep_BuzzerOFF();
		return;
	}

	// se é o beep acionado direto liga o buzzer e cai fora
	if (beep.type == beepCONTINUOUS) {
		beep_BuzzerON();
		return;
	}

	// respeitar o tempo entre emissão de beeps quando for de forma continua
	if (beep.interval) beep.interval--;
	else {
		if (beep.pulse[beep.index].tOn) { // Checa se ainda é tempo de ficar ativo o buzzer
			beep_BuzzerON(); // Liga o buzzer
			beep.pulse[beep.index].tOn--; // decrementa o tempo de permanecer ligado
		} else if (beep.pulse[beep.index].tOff) { // Checa se é ainda tempo de ficar desativo o buzzer
			beep_BuzzerOFF(); // desliga o buzzer
			beep.pulse[beep.index].tOff--; // decrementa o tempo de permanecer desligado
		// Vamos veriricar se fez todos os beeps e se é para tocar de forma continua o não,
		//	se sim vamos recomeçar, senão para tudo
		} else {
			if (beep.index < beep.nBeeps) // Checa se fez todos os beeps
				beep.index++; // vai para o próximo beep
			else {
				// se fez todos os beeps vamos checar se tem intervalo entre eles, se tiver vamos reiniciar
				// senão pata tudo
				if (beep.intervalLoad) {
					beep_SetType(); // reinicia as variáveis
					beep.interval = beep.intervalLoad; // Captura o intervalo
				} else beep.power = pdOFF; // desliga tudo
			}
		}
	}
}
